// Tool Execution Coordinator - 工具执行协调器
// 负责协调工具的注册、触发、执行流程

import { EventEmitter } from 'events';
import { ToolManager, ToolExecutionContext, ToolResult } from '@augment/tools';

export interface ChainExecutionContext extends ToolExecutionContext {
    previousResult?: any;
}

export interface ToolExecutionEvent {
    type: 'tool-start' | 'tool-progress' | 'tool-complete' | 'tool-error';
    toolName: string;
    requestId: string;
    timestamp: Date;
    data?: any;
    error?: Error;
}

export interface ToolExecutionRequest {
    requestId: string;
    toolName: string;
    parameters: Record<string, any>;
    context: ToolExecutionContext;
    priority?: number;
    timeout?: number;
}

export interface ToolExecutionResponse {
    requestId: string;
    toolName: string;
    result: ToolResult;
    executionTime: number;
    timestamp: Date;
}

/**
 * 工具执行协调器
 * 负责管理工具的执行队列、优先级、并发控制等
 */
export class ToolExecutionCoordinator extends EventEmitter {
    private toolManager: ToolManager;
    private executionQueue: ToolExecutionRequest[] = [];
    private activeExecutions = new Map<string, Promise<ToolExecutionResponse>>();
    private maxConcurrentExecutions: number = 5;
    private logger: any;

    constructor(toolManager: ToolManager, logger?: any) {
        super();
        this.toolManager = toolManager;
        this.logger = logger || console;
    }

    /**
     * 执行工具
     */
    async executeToolAsync(request: ToolExecutionRequest): Promise<ToolExecutionResponse> {
        const { requestId, toolName, parameters, context, timeout = 30000 } = request;

        // 检查工具是否可用
        if (!this.toolManager.isToolAvailable(toolName)) {
            throw new Error(`Tool ${toolName} is not available`);
        }

        // 发送开始事件
        this.emit('tool-execution', {
            type: 'tool-start',
            toolName,
            requestId,
            timestamp: new Date(),
            data: { parameters }
        } as ToolExecutionEvent);

        const startTime = Date.now();

        try {
            // 创建执行 Promise
            const executionPromise = this.executeWithTimeout(toolName, parameters, context, timeout);
            
            // 记录活跃执行
            this.activeExecutions.set(requestId, executionPromise);

            // 等待执行完成
            const response = await executionPromise;

            // 发送完成事件
            this.emit('tool-execution', {
                type: 'tool-complete',
                toolName,
                requestId,
                timestamp: new Date(),
                data: response
            } as ToolExecutionEvent);

            return response;

        } catch (error) {
            // 发送错误事件
            this.emit('tool-execution', {
                type: 'tool-error',
                toolName,
                requestId,
                timestamp: new Date(),
                error: error instanceof Error ? error : new Error(String(error))
            } as ToolExecutionEvent);

            throw error;

        } finally {
            // 清理活跃执行记录
            this.activeExecutions.delete(requestId);
        }
    }

    /**
     * 带超时的工具执行
     */
    private async executeWithTimeout(
        toolName: string,
        parameters: Record<string, any>,
        context: ToolExecutionContext,
        timeout: number
    ): Promise<ToolExecutionResponse> {
        const startTime = Date.now();

        return new Promise(async (resolve, reject) => {
            // 设置超时
            const timeoutId = setTimeout(() => {
                reject(new Error(`Tool ${toolName} execution timed out after ${timeout}ms`));
            }, timeout);

            try {
                // 执行工具
                const result = await this.toolManager.executeTool(toolName, parameters, context);
                
                clearTimeout(timeoutId);
                
                const response: ToolExecutionResponse = {
                    requestId: context.timestamp.getTime().toString(),
                    toolName,
                    result,
                    executionTime: Date.now() - startTime,
                    timestamp: new Date()
                };

                resolve(response);

            } catch (error) {
                clearTimeout(timeoutId);
                reject(error);
            }
        });
    }

    /**
     * 批量执行工具
     */
    async executeBatch(requests: ToolExecutionRequest[]): Promise<ToolExecutionResponse[]> {
        const results: ToolExecutionResponse[] = [];
        const errors: Error[] = [];

        // 按优先级排序
        const sortedRequests = requests.sort((a, b) => (b.priority || 0) - (a.priority || 0));

        // 分批执行，控制并发数
        for (let i = 0; i < sortedRequests.length; i += this.maxConcurrentExecutions) {
            const batch = sortedRequests.slice(i, i + this.maxConcurrentExecutions);
            
            const batchPromises = batch.map(async (request) => {
                try {
                    return await this.executeToolAsync(request);
                } catch (error) {
                    errors.push(error instanceof Error ? error : new Error(String(error)));
                    return null;
                }
            });

            const batchResults = await Promise.all(batchPromises);
            results.push(...batchResults.filter(result => result !== null) as ToolExecutionResponse[]);
        }

        if (errors.length > 0) {
            this.logger.warn(`Batch execution completed with ${errors.length} errors:`, errors);
        }

        return results;
    }

    /**
     * 取消工具执行
     */
    cancelExecution(requestId: string): boolean {
        const execution = this.activeExecutions.get(requestId);
        if (execution) {
            // 注意：这里只是从记录中移除，实际的工具执行可能仍在继续
            // 真正的取消需要工具本身支持取消机制
            this.activeExecutions.delete(requestId);
            
            this.emit('tool-execution', {
                type: 'tool-error',
                toolName: 'unknown',
                requestId,
                timestamp: new Date(),
                error: new Error('Execution cancelled')
            } as ToolExecutionEvent);

            return true;
        }
        return false;
    }

    /**
     * 获取活跃执行状态
     */
    getActiveExecutions(): string[] {
        return Array.from(this.activeExecutions.keys());
    }

    /**
     * 获取执行统计
     */
    getExecutionStats(): any {
        return {
            activeExecutions: this.activeExecutions.size,
            maxConcurrentExecutions: this.maxConcurrentExecutions,
            queueLength: this.executionQueue.length,
            toolStats: this.toolManager.getToolStats()
        };
    }

    /**
     * 设置最大并发执行数
     */
    setMaxConcurrentExecutions(max: number): void {
        this.maxConcurrentExecutions = Math.max(1, max);
    }

    /**
     * 清理资源
     */
    async cleanup(): Promise<void> {
        // 取消所有活跃执行
        const activeRequestIds = Array.from(this.activeExecutions.keys());
        for (const requestId of activeRequestIds) {
            this.cancelExecution(requestId);
        }

        // 清空队列
        this.executionQueue = [];

        // 移除所有监听器
        this.removeAllListeners();

        this.logger.info('ToolExecutionCoordinator cleaned up');
    }
}

/**
 * 工具执行流程管理器
 * 提供高级的工具执行流程控制
 */
export class ToolExecutionFlowManager {
    private coordinator: ToolExecutionCoordinator;
    private logger: any;

    constructor(toolManager: ToolManager, logger?: any) {
        this.logger = logger || console;
        this.coordinator = new ToolExecutionCoordinator(toolManager, logger);
        
        // 监听执行事件
        this.coordinator.on('tool-execution', this.handleToolExecutionEvent.bind(this));
    }

    /**
     * 处理工具执行事件
     */
    private handleToolExecutionEvent(event: ToolExecutionEvent): void {
        switch (event.type) {
            case 'tool-start':
                this.logger.info(`🚀 Tool ${event.toolName} started (${event.requestId})`);
                break;
            case 'tool-complete':
                this.logger.info(`✅ Tool ${event.toolName} completed (${event.requestId})`);
                break;
            case 'tool-error':
                this.logger.error(`❌ Tool ${event.toolName} failed (${event.requestId}):`, event.error);
                break;
            case 'tool-progress':
                this.logger.debug(`⏳ Tool ${event.toolName} progress (${event.requestId}):`, event.data);
                break;
        }
    }

    /**
     * 执行工具链
     * 按顺序执行多个工具，前一个工具的输出作为后一个工具的输入
     */
    async executeToolChain(
        tools: Array<{ name: string; parameters: Record<string, any> }>,
        context: ToolExecutionContext
    ): Promise<ToolExecutionResponse[]> {
        const results: ToolExecutionResponse[] = [];
        let chainContext: ChainExecutionContext = { ...context };

        for (const tool of tools) {
            const request: ToolExecutionRequest = {
                requestId: `chain_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
                toolName: tool.name,
                parameters: tool.parameters,
                context: chainContext
            };

            try {
                const response = await this.coordinator.executeToolAsync(request);
                results.push(response);

                // 更新链上下文，将前一个工具的结果传递给下一个工具
                if (response.result.success && response.result.data) {
                    chainContext = {
                        ...chainContext,
                        previousResult: response.result.data
                    };
                }

            } catch (error) {
                this.logger.error(`Tool chain execution failed at ${tool.name}:`, error);
                throw error;
            }
        }

        return results;
    }

    /**
     * 并行执行工具
     */
    async executeToolsParallel(
        tools: Array<{ name: string; parameters: Record<string, any> }>,
        context: ToolExecutionContext
    ): Promise<ToolExecutionResponse[]> {
        const requests: ToolExecutionRequest[] = tools.map(tool => ({
            requestId: `parallel_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
            toolName: tool.name,
            parameters: tool.parameters,
            context
        }));

        return await this.coordinator.executeBatch(requests);
    }

    /**
     * 获取协调器实例
     */
    getCoordinator(): ToolExecutionCoordinator {
        return this.coordinator;
    }

    /**
     * 清理资源
     */
    async cleanup(): Promise<void> {
        await this.coordinator.cleanup();
    }
}
